package com.xmut.mall.coupon.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.mall.coupon.dao.CouponDao;
import com.xmut.mall.coupon.entity.CouponEntity;
import com.xmut.mall.coupon.entity.PromotionGoodsEntity;
import com.xmut.mall.coupon.feign.MemberFeignService;
import com.xmut.mall.coupon.searchparams.BuyerCouponSearchParam;
import com.xmut.mall.coupon.searchparams.ManagerCouponSearchParam;
import com.xmut.mall.coupon.searchparams.SellerCouponSearchParam;
import com.xmut.mall.coupon.service.CouponService;
import com.xmut.mall.coupon.service.PromotionGoodsService;
import com.xmut.mall.coupon.utils.PageUtil;
import com.xmut.mall.coupon.utils.RespBean;
import com.xmut.mall.coupon.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service("couponService")
public class CouponServiceImpl extends ServiceImpl<CouponDao, CouponEntity> implements CouponService {

    @Autowired
    private PromotionGoodsService promotionGoodsService;

    @Autowired
    private MemberFeignService memberFeignService;

    /**
     * 添加优惠券
     *
     * @param vo
     * @return
     */
    @Override
    public RespBean addCoupon(AddCouponVo vo) {
        CouponEntity entity = new CouponEntity();
        Long id = IdWorker.getId(); // 当前coupon的Id
        entity.setId(id);
        entity.setPromotionName(vo.getPromotionName());
        entity.setCouponName(vo.getCouponName());
        entity.setDescription(vo.getDescription());
        entity.setCouponType(vo.getCouponType());
        entity.setCouponDiscount(vo.getCouponDiscount());
        entity.setPrice(vo.getPrice());
        entity.setGetType(vo.getGetType());
        entity.setPublishNum(vo.getPublishNum());
        entity.setConsumeThreshold(vo.getConsumeThreshold());
        entity.setCouponLimitNum(vo.getCouponLimitNum());
        entity.setReceivedNum(0);
        entity.setScopeType(vo.getScopeType());
        entity.setStartTime(vo.getStartTime());
        entity.setEndTime(vo.getEndTime());
        entity.setStoreId(vo.getStoreId());
        entity.setStoreName(vo.getStoreName());
        entity.setCreateTime(new Date());

        // 如果当前优惠券指定了使用范围
        if (vo.getScopeType().equals("PORTION_GOODS")) {
            entity.setScopeId(vo.getScopeId());
            // 向promotiongoods添加活动商品
            List<PromotionGoodsEntity> promotionGoodsList = vo.getPromotionGoodsList().stream().map(item -> {
                PromotionGoodsEntity promotionGoodsEntity = new PromotionGoodsEntity();
                promotionGoodsEntity.setStartTime(vo.getStartTime());
                promotionGoodsEntity.setEndTime(vo.getEndTime());
                promotionGoodsEntity.setGoodsName(item.getGoodsName());
                promotionGoodsEntity.setPrice(item.getPrice());
                promotionGoodsEntity.setPromotionId(id);
                promotionGoodsEntity.setPromotionType("COUPON");
                promotionGoodsEntity.setSkuId(item.getSkuId());
                promotionGoodsEntity.setThumbnail(item.getSkuDefaultImg());
                promotionGoodsEntity.setScopeType(vo.getScopeType());
                promotionGoodsEntity.setStoreId(vo.getStoreId());
                promotionGoodsEntity.setStoreName(vo.getStoreName());
                promotionGoodsEntity.setGoodsType("PHYSICAL_GOODS");
                promotionGoodsEntity.setCreateTime(new Date());
                return promotionGoodsEntity;
            }).collect(Collectors.toList());

            promotionGoodsService.saveBatch(promotionGoodsList);
        }

        // 如果当前优惠券指定了使用分类
        if (vo.getScopeType().equals("PORTION_GOODS_CATEGORY")) {
            entity.setScopeType(vo.getScopeType());
            entity.setScopeId(vo.getScopeId());
        }

        boolean save = this.save(entity);
        if (save) {
            return RespBean.success("添加成功");
        } else {
            return RespBean.error("添加失败");
        }

    }

    /**
     * 获取卖家端优惠券的分页数据
     *
     * @param vo
     * @param param
     * @return
     */
    @Override
    public RespBean getSellerCouponPage(PageVO vo, SellerCouponSearchParam param) {
        IPage<SellerCouponPageVo> page = this.baseMapper.getSellerCouponPage(PageUtil.initPage(vo), param, new Date());

        CouponEntity entity = new CouponEntity();
        for (SellerCouponPageVo record : page.getRecords()) {
            BeanUtils.copyProperties(record, entity);
            record.setPromotionStatus(entity.getPromotionStatus());
        }

        return RespBean.success("获取成功", page);
    }

    /**
     * 卖家端获取优惠券列表
     *
     * @param params
     * @return
     */
    @Override
    public RespBean sellerGetCouponList(Map<String, Object> params) {
        Long storeId = Long.parseLong(params.get("storeId").toString());
        String couponName = String.valueOf(params.get("couponName"));

        List<CouponEntity> couponEntityList = this.list(new QueryWrapper<CouponEntity>().eq("store_id", storeId));

        // 过滤一遍list 拿到现在进行中(可用的优惠券)
        List<CouponEntity> result = couponEntityList.stream()
                .filter(item -> item.getPromotionStatus().equals("START")).collect(Collectors.toList());


        return RespBean.success("获取成功", result);
    }

    /**
     * 根据ID获取优惠券详情
     *
     * @param id
     * @return
     */
    @Override
    public RespBean getCouponDetail(Long id) {
        AddCouponVo vo = new AddCouponVo();
        CouponEntity couponEntity = this.getById(id);
        BeanUtils.copyProperties(couponEntity, vo);
        if (couponEntity.getScopeType().equals("PORTION_GOODS")) {
            List<PromotionGoodsEntity> promotionGoodsList = promotionGoodsService
                    .list(new QueryWrapper<PromotionGoodsEntity>().eq("promotion_id", id));
            List<PromotionGoodsVo> result = promotionGoodsList.stream().map(item -> {
                PromotionGoodsVo promotionGoodsVo = new PromotionGoodsVo();
                BeanUtils.copyProperties(item, promotionGoodsVo);
                promotionGoodsVo.setSkuDefaultImg(item.getThumbnail());
                return promotionGoodsVo;
            }).collect(Collectors.toList());
            vo.setPromotionGoodsList(result);
        }
        return RespBean.success("获取成功", vo);
    }

    /**
     * 编辑优惠券
     *
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean editCoupon(AddCouponVo vo) {
        CouponEntity entity = new CouponEntity();
        BeanUtils.copyProperties(vo, entity);
        if (vo.getScopeType().equals("PORTION_GOODS")) {
            // 如果是指定了商品的情况 要把指定的商品一起更新
            List<PromotionGoodsEntity> promotionGoodsEntityList = vo.getPromotionGoodsList().stream().map(item -> {
                PromotionGoodsEntity promotionGoodsEntity = new PromotionGoodsEntity();
                promotionGoodsEntity.setId(item.getId());
                promotionGoodsEntity.setGoodsName(item.getGoodsName());
                promotionGoodsEntity.setPrice(item.getPrice());
                promotionGoodsEntity.setPromotionId(vo.getId());
                promotionGoodsEntity.setThumbnail(item.getSkuDefaultImg());
                promotionGoodsEntity.setSkuId(item.getSkuId());
                promotionGoodsEntity.setGoodsType("PHYSICAL_GOODS");
                promotionGoodsEntity.setPromotionType("COUPON");
                promotionGoodsEntity.setStartTime(vo.getStartTime());
                promotionGoodsEntity.setEndTime(vo.getEndTime());
                promotionGoodsEntity.setStoreId(item.getStoreId());
                promotionGoodsEntity.setStoreName(vo.getStoreName());
                promotionGoodsEntity.setCreateTime(new Date());
                return promotionGoodsEntity;
            }).collect(Collectors.toList());
            promotionGoodsService.saveOrUpdateBatch(promotionGoodsEntityList);
        }

        if (vo.getScopeType().equals("PORTION_GOODS_CATEGORY")) {
            // 如果改变了指定的分类就要删除活动商品里的指定商品
            promotionGoodsService.remove(new QueryWrapper<PromotionGoodsEntity>().eq("promotion_id", vo.getId()));
        }

        boolean b = this.updateById(entity);
        if (b) {
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }

    }

    /**
     * 关闭当前优惠券活动
     *
     * @param id
     * @return
     */
    @Override
    public RespBean closeCoupon(Long id) {
        boolean update = this.update(new UpdateWrapper<CouponEntity>()
                .set("start_time", null)
                .set("end_time", null)
                .eq("id", id));

        if (update) {
            return RespBean.success("关闭优惠券活动成功");
        } else {
            return RespBean.error("关闭优惠券活动失败");
        }
    }

    /**
     * 开启优惠券活动
     *
     * @param params
     * @return
     */
    @Override
    public RespBean openCoupon(Map<String, Object> params) {
        Long id = Long.parseLong(params.get("id").toString());
        Date startTime = new Date(Long.parseLong(params.get("startTime").toString()));
        Date endTime = new Date(Long.parseLong(params.get("endTime").toString()));

        boolean update = this.update(new UpdateWrapper<CouponEntity>()
                .set("start_time", startTime)
                .set("end_time", endTime)
                .eq("id", id));

        if (update) {
            return RespBean.success("开启成功");
        } else {
            return RespBean.error("开启失败");
        }

    }

    /**
     * 根据传入的Map参数获取
     *
     * @param params
     * @return
     */
    @Override
    public RespBean getManagerCouponList(Map<String, Object> params) {
        List<CouponEntity> list = this.list();
        return RespBean.success("获取成功", list);
    }

    /**
     * 获取商城管理端的优惠券分页数据 获取平台券
     *
     * @param vo
     * @param param
     * @return
     */
    @Override
    public RespBean getManagerCouponPage(PageVO vo, ManagerCouponSearchParam param) {
        IPage<ManagerCouponPageVo> page = this.baseMapper.getManagerCouponPage(PageUtil.initPage(vo), param, new Date());
        CouponEntity entity = new CouponEntity();
        for (ManagerCouponPageVo record : page.getRecords()) {
            BeanUtils.copyProperties(record, entity);
            record.setPromotionStatus(entity.getPromotionStatus());
        }
        return RespBean.success("获取分页数据成功", page);

    }

    /**
     * 添加平台优惠券(平台券)
     *
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean AddPlatformCoupon(AddPlatformCouponVo vo) {
        CouponEntity entity = new CouponEntity();
        Long id = IdWorker.getId();
        entity.setId(id);
        entity.setPromotionName(vo.getPromotionName());
        entity.setCouponName(vo.getCouponName());
        entity.setPrice(vo.getPrice());
        entity.setReceivedNum(0);
        entity.setCouponType(vo.getCouponType());
        entity.setDescription(vo.getDescription());
        entity.setGetType(vo.getGetType());
        entity.setConsumeThreshold(vo.getConsumeThreshold());
        entity.setCouponLimitNum(vo.getCouponLimitNum());
        entity.setPublishNum(vo.getPublishNum());
        entity.setRangeDayType(vo.getRangeDayType());
        entity.setScopeType(vo.getScopeType());
        entity.setStoreCommission(vo.getStoreCommission());
        entity.setStartTime(vo.getStartTime());
        entity.setEndTime(vo.getEndTime());
        entity.setStoreId(vo.getStoreId());
        entity.setStoreName(vo.getStoreName());
        entity.setCreateTime(new Date());

        // 如果是折扣类型
        if (vo.getCouponType().equals("DISCOUNT")) {
            entity.setCouponDiscount(vo.getCouponDiscount());
        }

        // 如果是从活动获取
        if (vo.getGetType().equals("ACTIVITY")) {
            entity.setGetType(vo.getGetType());
        }

        // 如果指定了可使用的分类
        if (vo.getScopeType().equals("PORTION_GOODS_CATEGORY")) {
            entity.setScopeId(vo.getScopeId());
            entity.setScopeType(vo.getScopeType());
        }

        // 如果指定了可使用的商品
        if (vo.getScopeType().equals("PORTION_GOODS")) {
            entity.setScopeId(vo.getScopeId());
            // 向promotiongoods添加活动商品
            List<PromotionGoodsEntity> promotionGoodsList = vo.getPromotionGoodsList().stream().map(item -> {
                PromotionGoodsEntity promotionGoodsEntity = new PromotionGoodsEntity();
                promotionGoodsEntity.setStartTime(vo.getStartTime());
                promotionGoodsEntity.setEndTime(vo.getEndTime());
                promotionGoodsEntity.setGoodsName(item.getGoodsName());
                promotionGoodsEntity.setPrice(item.getPrice());
                promotionGoodsEntity.setPromotionId(id);
                promotionGoodsEntity.setPromotionType("COUPON");
                promotionGoodsEntity.setSkuId(item.getSkuId());
                promotionGoodsEntity.setThumbnail(item.getSkuDefaultImg());
                promotionGoodsEntity.setScopeType(vo.getScopeType());
                promotionGoodsEntity.setStoreId(vo.getStoreId());
                promotionGoodsEntity.setStoreName(vo.getStoreName());
                promotionGoodsEntity.setGoodsType("PHYSICAL_GOODS");
                promotionGoodsEntity.setCreateTime(new Date());
                return promotionGoodsEntity;
            }).collect(Collectors.toList());

            promotionGoodsService.saveBatch(promotionGoodsList);
        }

        boolean save = this.save(entity);
        if (save) {
            return RespBean.success("保存成功");
        } else {
            return RespBean.error("保存失败");
        }
    }

    /**
     * 根据ID获取平台券的详情
     *
     * @param id
     * @return
     */
    @Override
    public RespBean getPlatformCouponDetail(Long id) {
        AddPlatformCouponVo vo = new AddPlatformCouponVo();
        CouponEntity entity = this.getById(id);
        BeanUtils.copyProperties(entity, vo);

        if (entity.getScopeType().equals("PORTION_GOODS")) {
            // 如果该优惠券指定了使用的商品;
            List<PromotionGoodsEntity> promotionGoodsEntityList = promotionGoodsService
                    .list(new QueryWrapper<PromotionGoodsEntity>()
                            .eq("promotion_id", id));
            List<PromotionGoodsVo> result = promotionGoodsEntityList.stream().map(item -> {
                PromotionGoodsVo promotionGoodsVo = new PromotionGoodsVo();
                BeanUtils.copyProperties(item, promotionGoodsVo);
                promotionGoodsVo.setSkuDefaultImg(item.getThumbnail());
                return promotionGoodsVo;
            }).collect(Collectors.toList());
            vo.setPromotionGoodsList(result);
        }

        return RespBean.success("获取成功", vo);
    }

    /**
     * 编辑平台券的内容
     *
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean editPlatformCoupon(AddPlatformCouponVo vo) {
        CouponEntity entity = new CouponEntity();
        BeanUtils.copyProperties(vo, entity);
        if (vo.getScopeType().equals("PORTION_GOODS")) {
            // 如果是指定了商品的情况 要把指定的商品一起更新
            List<PromotionGoodsEntity> promotionGoodsEntityList = vo.getPromotionGoodsList().stream().map(item -> {
                PromotionGoodsEntity promotionGoodsEntity = new PromotionGoodsEntity();
                promotionGoodsEntity.setId(item.getId());
                promotionGoodsEntity.setGoodsName(item.getGoodsName());
                promotionGoodsEntity.setPrice(item.getPrice());
                promotionGoodsEntity.setPromotionId(vo.getId());
                promotionGoodsEntity.setThumbnail(item.getSkuDefaultImg());
                promotionGoodsEntity.setSkuId(item.getSkuId());
                promotionGoodsEntity.setGoodsType("PHYSICAL_GOODS");
                promotionGoodsEntity.setPromotionType("COUPON");
                promotionGoodsEntity.setStartTime(vo.getStartTime());
                promotionGoodsEntity.setEndTime(vo.getEndTime());
                promotionGoodsEntity.setStoreId(item.getStoreId());
                promotionGoodsEntity.setStoreName(vo.getStoreName());
                promotionGoodsEntity.setCreateTime(new Date());
                return promotionGoodsEntity;
            }).collect(Collectors.toList());
            promotionGoodsService.saveOrUpdateBatch(promotionGoodsEntityList);
        }

        if (vo.getScopeType().equals("PORTION_GOODS_CATEGORY")) {
            // 如果改变了指定的分类就要删除活动商品里的指定商品
            promotionGoodsService.remove(new QueryWrapper<PromotionGoodsEntity>().eq("promotion_id", vo.getId()));
        }

        boolean b = this.updateById(entity);
        if (b) {
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }
    }

    /**
     * 删除优惠券
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean deleteCoupon(Long id) {
        CouponEntity entity = this.getById(id);

        if (entity.getScopeType().equals("PORTION_GOODS")) {
            // 如果有指定使用商品的范围 那就要先删除该范围商品记录
            promotionGoodsService.remove(new QueryWrapper<PromotionGoodsEntity>().eq("promotion_id", id));
        }

        // 删除本体
        boolean b = this.removeById(id);
        if (b) {
            return RespBean.success("删除成功");
        } else {
            return RespBean.error("删除失败");
        }

    }

    /**
     * 获取商品详情中的优惠券信息
     *
     * @param skuId
     * @param cateId
     * @return
     */
    @Override
    public RespBean getProductDetailCoupon(Long skuId, Long cateId) {
        List<CouponEntity> result = new ArrayList<>();
        // 获取全部正在进行中的优惠券
        List<CouponEntity> STARCoupon = this.list(new QueryWrapper<CouponEntity>()
                .lt("start_time", new Date()).gt("end_time", new Date()));

        // 过滤出来属于全部可用的优惠券
        List<CouponEntity> allUseCoupon = STARCoupon.stream().filter(item -> {
            return item.getScopeType().equals("ALL");
        }).collect(Collectors.toList());
        for (CouponEntity entity : allUseCoupon) {
            // set进结果集
            result.add(entity);
        }

        // 过滤出当前sku的分类cateId可用的优惠券
        List<CouponEntity> PORTION_GOODS_CATEGORY_Coupon = STARCoupon.stream().filter(item -> {
            return item.getScopeType().equals("PORTION_GOODS_CATEGORY");
        }).collect(Collectors.toList());
        for (CouponEntity entity : PORTION_GOODS_CATEGORY_Coupon) {
            ArrayList<String> strings = CollUtil.newArrayList(entity.getScopeId().split(","));
            if (strings.equals(String.valueOf(cateId))) {
                // 如果当前的scopeid的分类id和传入的cateid一致就把优惠券加入
                result.add(entity);
            }
        }

        // 过滤出来可用的优惠券中属于特指商品的优惠券
        List<CouponEntity> PORTION_GOODS_Coupon = STARCoupon.stream().filter(item -> {
            return item.getScopeType().equals("PORTION_GOODS");
        }).collect(Collectors.toList());
        // 获取活动商品中属于该skuId的数据源
        List<PromotionGoodsEntity> promotionGoodsEntities = promotionGoodsService
                .list(new QueryWrapper<PromotionGoodsEntity>().eq("sku_id", skuId));
        // 收集活动的Id
        List<Long> promotionIds = promotionGoodsEntities.stream()
                .map(PromotionGoodsEntity::getPromotionId).collect(Collectors.toList());
        // 在PORTION_GOODS_Coupon查找ID相同的
        for (CouponEntity entity : PORTION_GOODS_Coupon) {
            for (Long promotionId : promotionIds) {
                if (entity.getId().equals(promotionId)) {
                    // 如果他们的Id匹配就加入结果
                    result.add(entity);
                }
            }
        }

        return RespBean.success("获取成功", result);
    }

    /**
     * 根据商铺Id获取购物车中可用的优惠券
     *
     * @param storeId
     * @return
     */
    @Override
    public RespBean getCartShopCoupon(Long storeId) {
        // 获取正在进行的 并且属于该店铺的优惠券
        List<CouponEntity> couponList = this.list(new QueryWrapper<CouponEntity>()
                .lt("start_time", new Date())
                .gt("end_time", new Date())
                .eq("scope_type", "ALL")
                .eq("store_id", storeId));

        return RespBean.success("获取成功", couponList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean receiveCoupon(Map<String, Object> params) {
        Long couponId = MapUtil.getLong(params, "couponId");
        Long userId = MapUtil.getLong(params, "userId");
//        Integer num = MapUtil.getInt(params, "num");// 领取数量

        CouponEntity coupon = this.getById(couponId);
        if (coupon.getPublishNum()<=0){
            return RespBean.error("该优惠券已经领完了");
        }
        RespBean userReceiveCouponNumResp = memberFeignService.getUserReceiveCouponNum(couponId, userId);
        // 查询用户领取了几次
        Integer userReceiveNum = JSON.parseObject(JSON.toJSONString(userReceiveCouponNumResp.getObj()), Integer.class);
        // 进行前置判断
        if (userReceiveNum >= coupon.getCouponLimitNum()) {
            return RespBean.error("超过当前优惠券领取上限");
        }

        // 进行领取
        RespBean userReceiveCouponResp = memberFeignService.userReceiveCoupon(params);
        if (userReceiveCouponResp.getCode() == 201) {
            // 扣减当前优惠券数量
            this.update(new UpdateWrapper<CouponEntity>()
                    .set("publish_num",coupon.getPublishNum()-1)
                    .eq("id",coupon.getId()));
            return RespBean.success("领取成功");
        } else {
            return RespBean.error("领取失败");
        }
    }

    /**
     * 获取买家端的优惠券分页数据
     * @param vo
     * @param param
     * @return
     */
    @Override
    public RespBean getBuyerCouponPage(PageVO vo, BuyerCouponSearchParam param) {
        IPage<CouponEntity> page = this.baseMapper.getBuyerCouponPage(PageUtil.initPage(vo),param,new Date());

        return RespBean.success("获取成功",page);
    }

    /**
     * 领取优惠券后减少优惠券数量
     * @param params
     * @return
     */
    @Override
    public RespBean reduceCouponNum(Map<String, Object> params) {
        Long couponId = MapUtil.getLong(params, "couponId");
        Integer num = MapUtil.getInt(params, "num");// 领取数量
        CouponEntity entity = this.getById(couponId);
        boolean update = this.update(new UpdateWrapper<CouponEntity>()
                .set("received_num", entity.getReceivedNum() + num)
                .eq("id", couponId));
        if (update){
            return RespBean.success("修改成功");
        }else {
            return RespBean.error("修改失败");
        }
    }


}
